package ultimaVersion;
import java.util.ArrayList;



public class PuertoSerie implements GestorDePuertos,NormaRs232{
	
	/**
	 * Variable de control del puerto con 0 desactivado, 1 lectura habilitada, -1 escritura habilitada
	 */
	private static int estado;
	
	/** 
	 * Variable de control de velocidadDeTransferencia del puerto
	 */
	private long velocidadDeTransferencia;
	
	/**
	 * Variable que reprecenta la direccion de memoria del bit de la entrada y salida
	 * de datos
	 */
	private static boolean puerto;
	
	/**
	 * Almacen de la entrada y salida del byte
	 */
	private ArrayList<Boolean> buffer;

	
	/**El constructor crea el buffer, setea la velocidad en 1 y bloquea el puerto
	 * */
	public PuertoSerie() {
		super();
		this.velocidadDeTransferencia = 1;
		this.buffer = new ArrayList<Boolean>();
		PuertoSerie.estado=0;
		
	}

	/** Devuelve la velocidad de transferencia actual
	 **/
	public long getVelocidadDeTransferencia() {
		return velocidadDeTransferencia;
	}

		
	/**Si el estado esta en 1 trae bits de a uno desde el puerto al buffer. Si esta en -1 
	 * escribe los bits de a uno al puerto desde el buffer
	 */
	public boolean transferir(int n){
			int i=0;
			GeneradorRs232 transmisor = new GeneradorRs232();
			String temp=new String(String.valueOf(1000/velocidadDeTransferencia));
			Long tiempo= new Long(temp);
			if(PuertoSerie.estado==1){
				if(!this.buffer.isEmpty())this.buffer.removeAll(buffer);//Si va a leer borra buffer
				}
			do{	
				if(PuertoSerie.estado==1){
					PuertoSerie.puerto=transmisor.nuevoBit();
					this.buffer.add(new Boolean(puerto));
				}
				else if(PuertoSerie.estado==-1)PuertoSerie.puerto=this.buffer.get(i).booleanValue();
				else return false;
				try {
					Thread.sleep(tiempo);
				} catch (InterruptedException e) {
					System.out.print("No se pudo sincronizar con el dispositivo...");
					return false;
					}
				i++;
			}while(i<n);
			return true;
 		}

	/**Si lee el puerto verifica los bits de inicio, fin y paridad. Luego los quita del buffer, sino devuelve false.
	 * Se escribe, coloca los bits de inicio, fin y paridad, luego devuelve true.
	 * */	
	private boolean verifRs232() {
		Boolean ini=false;
		Boolean fin=false;
		float cont=0;
		int i;
		if(PuertoSerie.estado==1){
			ini=this.buffer.remove(0);
			for (i=0;i<(buffer.size()-2);i++)
				if(buffer.get(i).booleanValue())cont++;
			boolean paridad=buffer.remove(i).booleanValue();
			boolean b2;
			if((Math.round(cont/2))==(cont/2))b2=true; else b2=false;
			if(paridad!=b2)return false;
			fin=buffer.remove(i);
			if((ini==false)&&(fin==false))return true;
			else return false;
			}
		else if(PuertoSerie.estado==-1){
			buffer.add(0, ini);
			for (i=1;i<buffer.size();i++)
				if(buffer.get(i).booleanValue())cont++;
			float par = cont/2;
			buffer.add(Boolean.valueOf((Math.round(par))==par));
			buffer.add(fin);
			return true;
			}
		else return false;
	}

	/** 
	 * Setter of the property <tt>velocidadDeTransferencia</tt>
	 */
	public void setVelocidadDeTransferencia(long velocidadDeTransferencia) {
		this.velocidadDeTransferencia = velocidadDeTransferencia;
	}


	/**Devuelve un arraylist del bufer 
	 **/
	public ArrayList<Boolean> getBuffer() {
		return buffer;
	}

	/**Cambia el arraylist del bufer por un arraylist de la celda de memoria
	 **/
	public boolean setBuffer(ArrayList<Boolean> contCelda) {
		if(contCelda.isEmpty())return false;
		if(!buffer.isEmpty())this.buffer.clear();
		for(int i=0;i<contCelda.size();i++)
			buffer.add(contCelda.get(i));
		return true;
	}


	/**Devuelve el estado del puerto con 0 desactivado, 1 lectura habilitada,
	 *  -1 escritura habilitada
	 */
	public int getEstado() {
		return estado;
	}

	/** Setea el estado del puerto con 0 desactivado, 1 lectura habilitada,
	 *  -1 escritura habilitada
	 * */
	public void setEstado(int estado) {
		PuertoSerie.estado = estado;
	}
	
	/**Cierra el puerto
	 * */
	public void cerrarTransferencia() {
		PuertoSerie.estado=0;
	}

	public boolean transferirBajoNorma(int n) {
		int i=0;
		GeneradorRs232 transmisor = new GeneradorRs232();
		String temp=new String(String.valueOf(1000/velocidadDeTransferencia));
		Long tiempo= new Long(temp);
		if(PuertoSerie.estado==1){
			if(!this.buffer.isEmpty())this.buffer.removeAll(buffer);//Si va a leer borra buffer
			}
	 	else if(PuertoSerie.estado==-1){
	 		if(!verifRs232())return false;//Si va a escribir agrega rs232
	 		}
		do{	
			if(PuertoSerie.estado==1){
				PuertoSerie.puerto=transmisor.nuevoBit();
				this.buffer.add(new Boolean(puerto));
			}
			else if(PuertoSerie.estado==-1)PuertoSerie.puerto=this.buffer.get(i).booleanValue();
			else return false;
			try {
				Thread.sleep(tiempo);
			} catch (InterruptedException e) {
				System.out.print("No se pudo sincronizar con el dispositivo...");
				return false;
				}
			i++;
		}while(i<n+3);
		int ant=estado;
		PuertoSerie.estado=1;//Cambia el estado para asegurar la quita de rs232
		boolean b= verifRs232();//si leyo, verif y borra rs232.
		PuertoSerie.estado=ant;//vuelve al estado anterior.
		return b;
	}



}
